#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    plot=nullptr;
    ui->setupUi(this);
    //输入点坐标事件绑定
    connect(ui->act_inputPoint,SIGNAL(triggered()),this,SLOT(openAddPointWin()));
    connect(ui->btn_inputPoint,SIGNAL(clicked()),this,SLOT(openAddPointWin()));
    //设置对话框事件绑定
    connect(ui->act_settings,SIGNAL(triggered()),this,SLOT(openSettings()));
    //打开文件事件绑定
    connect(ui->act_openFile,SIGNAL(triggered()),this,SLOT(openFileDlg()));
    connect(ui->btn_openFile,SIGNAL(clicked()),this,SLOT(openFileDlg()));
    //
    connect(ui->act_savePoint,SIGNAL(triggered()),this,SLOT(savePoints()));
    connect(ui->btn_savePoint,SIGNAL(clicked()),this,SLOT(savePoints()));
    //
    connect(ui->btn_startPlan,SIGNAL(clicked()),this,SLOT(startCalc()));
    //
    connect(ui->act_saveFile,SIGNAL(triggered()),this,SLOT(saveLog()));
    connect(ui->btn_saveResult,SIGNAL(clicked()),this,SLOT(saveLog()));
    //
    readSets();
    //
    plot=new QCustomPlot();
    ui->picResult->addWidget(plot);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::drawPoints(const QVector<Point> &ps)
{
    if(plot!=nullptr) plot->deleteLater();
    plot=new QCustomPlot();
    ui->picResult->addWidget(plot);

    QVector<double> xArr,yArr;
    for(auto i:ps){
        xArr.push_back(i.getX());
        yArr.push_back(i.getY());
    }

    auto xMax=*std::max_element(std::begin(xArr),std::end(xArr));
    auto xMin=*std::min_element(std::begin(xArr),std::end(xArr));
    auto yMax=*std::max_element(std::begin(yArr),std::end(yArr));
    auto yMin=*std::min_element(std::begin(yArr),std::end(yArr));

    plot->xAxis->setRange(xMin-2,xMax+2);
    plot->yAxis->setRange(yMin-2,yMax+2);
    QPen drawPen;
    drawPen.setColor(Qt::red);
    drawPen.setWidth(4);

    graphC=new QCPCurve(plot->xAxis,plot->yAxis);
    graphC->setLineStyle(QCPCurve::lsNone);
    graphC->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 4));
    graphC->setPen(drawPen);

    graphC->setData(xArr,yArr);
    plot->replot();
}

void MainWindow::drawResult(const QVector<int> &points)
{
    if(plot!=nullptr) plot->deleteLater();
    plot=new QCustomPlot();
    ui->picResult->addWidget(plot);

    QVector<double> xArr,yArr;
    for(auto i:points){
        auto x=pointArr[i].getX();
        auto y=pointArr[i].getY();
        xArr.push_back(x);
        yArr.push_back(y);
    }
    xArr.push_back(xArr.at(0));
    yArr.push_back(yArr.at(0));

    auto xMax=*std::max_element(std::begin(xArr),std::end(xArr));
    auto xMin=*std::min_element(std::begin(xArr),std::end(xArr));
    auto yMax=*std::max_element(std::begin(yArr),std::end(yArr));
    auto yMin=*std::min_element(std::begin(yArr),std::end(yArr));

    plot->xAxis->setRange(xMin-2,xMax+2);
    plot->yAxis->setRange(yMin-2,yMax+2);
    QPen drawPen;
    drawPen.setColor(Qt::red);
    drawPen.setWidth(4);

    graphC=new QCPCurve(plot->xAxis,plot->yAxis);
    graphC->setLineStyle(QCPCurve::lsLine);
    graphC->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 4));
    graphC->setPen(drawPen);

    graphC->setData(xArr,yArr);
    plot->replot();
}

void MainWindow::openAddPointWin(){
    //调用输入坐标窗口
    addPointDlg dlg(&this->pointArr);
    connect(&dlg,SIGNAL(pointChanged()),this,SLOT(rePaint()));
    dlg.exec();
}

void MainWindow::openSettings()
{
    //调用设置窗口
    readSets();
    SettingsDlg dlg(&this->sets);
    connect(&dlg,SIGNAL(accepted()),this,SLOT(updateSets()));
    dlg.exec();
}

void MainWindow::openFileDlg()
{
    //准备打开文件 弹出打开文件对话框
    QString url=QFileDialog::getOpenFileName(this,"打开点坐标文件","","Point File(*.pdat)");
    this->readTh=new ReadFileThread(url);
    qRegisterMetaType<QVector<Point>>("QVector<Point>");
    connect(readTh,SIGNAL(readFinished(QVector<Point>)),this,SLOT(onPointReadFinished(QVector<Point>)));
    this->readTh->start();
}

void MainWindow::onPointReadFinished(QVector<Point> arr)
{
    this->pointArr=arr;
    this->drawPoints(this->pointArr);
    delete this->readTh;
}

void MainWindow::rePaint()
{
    this->drawPoints(this->pointArr);
}

void MainWindow::saveLog()
{
    auto file=QFileDialog::getSaveFileName(this,tr("保存结果文件"),QString(),QString("文本文件(*.txt)"));
    if(file.isNull()) return;
    QFile *saveFile;
    saveFile=new QFile(file);
    if(saveFile->open(QIODevice::WriteOnly|QIODevice::Text)){
        auto arr=ui->textResult->toPlainText().toUtf8();
        saveFile->write(arr);
    }
    saveFile->close();
    saveFile->deleteLater();
}

void MainWindow::savePoints()
{
    if(pointArr.isEmpty()){
        QMessageBox::critical(this,"Err","点坐标为空");
        return;
    }
    auto file=QFileDialog::getSaveFileName(this,tr("保存点文件"),QString(),QString("点坐标文件(*.pdat)"));
    if(file.isNull()) return;
    QFile *saveFile;
    saveFile=new QFile(file);
    if(saveFile->open(QIODevice::WriteOnly|QIODevice::Text)){
        for(int i=0;i<pointArr.size();i++){
            QString str(QString::number(i)+" "+QString::number(pointArr.at(i).getX())+" "+QString::number(pointArr.at(i).getY())+"\n");
            saveFile->write(str.toUtf8());
        }
    }
    saveFile->close();
    saveFile->deleteLater();
}

void MainWindow::startCalc()
{
    if(pointArr.isEmpty()){
        QMessageBox::critical(this,"Err","点坐标为空");
        return;
    }
    else if(pointArr.size()<4){
        QMessageBox::critical(this,"Err","点太少了");
        return;
    }
    this->taskTh=new RunTaskThread(&pointArr,static_cast<int>(sets[0]),sets[1],sets[2],sets[3]);
    connect(this->taskTh,SIGNAL(tTaskFinished(QVector<int>, QString)),this,SLOT(onCalcFinished(QVector<int>, QString)));
    this->taskTh->start();
    dlg=new waitDlg();
    dlg->exec();
}

void MainWindow::onCalcFinished(QVector<int>res, QString resStr)
{
    QVector<Point> points;
    for(auto i : res){
        points.push_back(this->pointArr[i]);
    }
    drawResult(res);
    this->pointArr=points;
    ui->textResult->clear();
    ui->textResult->setText(resStr);
    dlg->close();
    dlg->deleteLater();
    dlg=nullptr;
}

void MainWindow::updateSets()
{
    QFile f("config");
    if(f.open(QIODevice::WriteOnly)){
        QDataStream s(&f);
        s<<sets;
        f.close();
    }
}

void MainWindow::readSets()
{
    QFileInfo info;
    info.setFile("config");
    if(!info.exists()){
        this->sets.clear();
        this->sets={100,100,1,0.98};
        QFile f("config");
        if(f.open(QIODevice::WriteOnly)){
            QDataStream s(&f);
            s<<sets;
            f.close();
        }
    }
    else{
        QFile f("config");
        if(f.open(QIODevice::ReadOnly)){
            QDataStream s(&f);
            s>>sets;
            f.close();
        }
    }
}

void ReadFileThread::run()
{
    QFile *pointFile;
    //判断是否选择了文件 若选择了 打开它
    if(this->file.isNull()) return;
    pointFile=new QFile(file);
    //进行读取
    if(pointFile->open(QIODevice::ReadOnly|QIODevice::Text)){
        QByteArray t;
        while(!pointFile->atEnd()){//未读到文件尾部
            //读取一行
            t=pointFile->readLine();
            QString t_str(t);
            //按空格分割
            auto tarrs=t_str.split(' ');
            //构建点对象
            Point p(tarrs[1].toDouble(),tarrs[2].toDouble());
            pointArr.push_back(p);
        }
    }
    //释放文件和对象内存
    pointFile->close();
    pointFile->deleteLater();
    pointFile=nullptr;
    emit readFinished(pointArr);
}
